package com.qk.service.impl;

import com.qk.common.Result;
import com.qk.mapper.OssCleanupRecordMapper;
import com.qk.mapper.UserMapper;
import com.qk.service.OssCleanupService;
import com.qk.utils.AliyunOSSOperators;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 28188
 */
@Slf4j
@Service
public class OssCleanupServiceImpl implements OssCleanupService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OssCleanupRecordMapper ossCleanupRecordMapper;
    @Autowired
    private AliyunOSSOperators aliyunOSSOperators;

    @Override
    @Scheduled(cron = "0 0 2 * * ?")
    public Integer cleanupUnusedImages() {
        log.info("开始清理oss无用图片");
        LocalDateTime lastCleanupTime = getLastCleanupTime();
        Set<String> filesToDelete = getFilesToDelete(lastCleanupTime);
        Integer deletedCount = aliyunOSSOperators.deleteFiles(filesToDelete);
        // 记录清理历史
        ossCleanupRecordMapper.saveCleanupRecord(LocalDateTime.now(), deletedCount);
        return deletedCount;
    }

    @Override
    public Object previewCleanup() {
        try {
            LocalDateTime lastCleanupTime = getLastCleanupTime();
            Set<String> filesToDelete = getFilesToDelete(lastCleanupTime);
            Map<String, Object> preview = new HashMap<>();
            preview.put("orphanFiles", filesToDelete.size());
            preview.put("filesToDelete", filesToDelete);
            return preview;
        } catch (Exception e) {
            log.error("预览失败", e);
            return Result.error("预览失败: " + e.getMessage());
        }
    }

    /**
     * 获取需要删除的文件集合
     * 该方法通过对比数据库中的图片URL和OSS中的文件Key，找出存在于OSS但不存在于数据库中的文件
     * 这些文件被认为是无用的，可以被安全删除
     *
     * @return 返回需要删除的文件Key集合
     */
    private Set<String> getFilesToDelete(LocalDateTime sinceTime) {
        // 查询数据库中所有图片URL
        Set<String> dbImageUrls = userMapper.selectImageUrlsSince(sinceTime);
        // 将图片URL转换为文件Key
        Set<String> dbFileKeys = dbImageUrls.stream()
                .map(url -> extractFileKeyByPrefix(url, aliyunOSSOperators.getUrlPrefixLength()))
                .collect(Collectors.toSet());
        // 查询oss中所有图片
        Set<String> ossFileKeys = aliyunOSSOperators.getOssFileKeys(null, sinceTime);
        // 找出无用的图片
        return ossFileKeys.stream()
                .filter(fileKey -> !dbFileKeys.contains(fileKey))
                .collect(Collectors.toSet());
    }

    /**
     * 根据前缀长度截取文件key
     */
    private String extractFileKeyByPrefix(String fileUrl, int prefixLength) {
        if (!StringUtils.hasText(fileUrl) || fileUrl.length() <= prefixLength) {
            return null;
        }
        return fileUrl.substring(prefixLength);
    }

    // 获取上一次清理时间，防空指针
    private LocalDateTime getLastCleanupTime() {
        if (ossCleanupRecordMapper.selectLatestRecord() == null) {
            return null;
        }
        return ossCleanupRecordMapper.selectLatestRecord().getLastCleanupTime();
    }


}
